/*
 * Путь на клетчатом поле
 */

#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <assert.h>

#ifdef DEBUG
# define debug_fprintf(x)	fprintf x
#else
# define debug_fprintf(x)	((void) 0)
#endif

/* my pathetic attempt at writing soft-assert */
#define S_assert(st) ((st)?((void)0):(void)fprintf(stderr,"Assertion (soft) \"%s\" in %s:%s():%d: failed.\n",#st,__FILE__,__func__,__LINE__))

#define MAX(a, b)	((a)>(b)?(a):(b))
#define MIN(a, b)	((a)<(b)?(a):(b))

/* queue */
struct queue {
	char *data;
	size_t _data_size;

	int head;
	int n;
	int _max;
};

struct tile {
	bool visited;
	bool enqueued;
	bool avail;
	bool _b1;

	int distance;
};

struct point {
	int x;
	int y;
};

/*
static struct point _d[] = { { .x =  1, .y =  0 },
                             { .x =  0, .y =  1 },
			     { .x = -1, .y =  0 },
			     { .x =  0, .y = -1 }  };
 */
static struct point _d[] = { {  1,  0 },
                             {  0,  1 },
			     { -1,  0 },
			     {  0, -1 }  };

/* {{{ memory allocation wrappers */
extern void *s_calloc(size_t n, size_t size)
{
	void *ptr;
	ptr = calloc(n, size);
	assert(ptr != NULL);
	if (ptr == NULL) {
		debug_fprintf((stderr, "out of memory\n"));
		abort();
	}
	return ptr;
}

extern void *s_malloc(size_t size)
{
	void *ptr;
	ptr = malloc(size);
	assert(ptr != NULL);
	if (ptr == NULL) {
		debug_fprintf((stderr, "out of memory\n"));
		abort();
	}
	return ptr;
}
/* }}} */

/* {{{ queue */
extern struct queue *
queue__new(const int n, const size_t elem_size)
{
	struct queue *q = NULL;

	assert(n > 1);
	assert(elem_size > 0);

	q = (struct queue *) s_malloc(sizeof *q);
	q->data = (char *) s_calloc(n, elem_size);
	q->_data_size = elem_size;
	q->head = 0;
	q->n = 0;
	q->_max = n;

	return q;
}

extern int
queue__push(struct queue *q, const void *p)
{
	assert(q != NULL);
	assert(p != NULL);

	if (q->n >= q->_max) {
		debug_fprintf((stderr, "%s(): q->n (%d) >= q->_max (%d), can't push any deeper :-(\n",
				__func__, q->n, q->_max));
		return -1; /* can't push any further */
	}

	memcpy(q->data + ((q->head + q->n++) % q->_max) * q->_data_size, p, q->_data_size);
	debug_fprintf((stderr, "%s(): q->head=%d, q->n=%d\n",
			__func__, q->head, q->n));

	return 0;
}

extern int
queue__pop(struct queue *q, void *buf)
{
	assert(q != NULL);
	assert(buf != NULL);

	memcpy(buf, q->data + (q->head) * q->_data_size, q->_data_size);
	q->head = (q->head + 1) % q->_max;
	q->n--;
	debug_fprintf((stderr, "%s(): q->head=%d, q->n=%d\n",
			__func__, q->head, q->n));

	return 0;
}

extern int
queue__cleanup(struct queue *q)
{
	S_assert(q != NULL);
	if (q == NULL)
		return -1;

	if (q->_max == 0 || q->data == NULL)
		return 1;

	free(q->data);
	q->data = NULL;
	free(q);

	return 0;
}
/* }}} */

void
print_field(struct tile **f)
{
	int i, j;
	for (i = 0; i < 41; i += 1) {
		for (j = 0; j < 41; j += 1) {
			/*fputc('0' + f[j][i].avail + f[j][i].visited, stderr);*/
			fprintf(stderr, "%2d ", f[j][i].distance);
		}
		fputc('\n', stderr);
	}
	fputc('\n', stderr);
}

int
bfs_find_distance_grid(struct tile **f, const int sx, const int sy, const int fx, const int fy)
{
	struct queue *q;
	struct point pt;
	struct point ptnxt;
	int i;
	int ret = 0;

	q = queue__new(41 * 41, sizeof pt);
	pt.x = sx * 2;
	pt.y = sy * 2;
	S_assert(f[pt.x][pt.y].avail == true);
	queue__push(q, &pt);

	while (q->n) {
		queue__pop(q, &pt);
#ifdef DEBUG
		print_field(f);
#endif
		f[pt.x][pt.y].visited = true;

		if (pt.x == fx * 2 && pt.y == fy * 2) {
			ret = 1;
			break;
		}

		for (i = 0; i < sizeof _d / sizeof _d[0]; i++) {
			if (pt.x + _d[i].x >= 0 && pt.x + _d[i].x < 41 &&
			    pt.y + _d[i].y >= 0 && pt.y + _d[i].y < 41 &&
			    f[pt.x + _d[i].x][pt.y + _d[i].y].enqueued == false &&
			    f[pt.x + _d[i].x][pt.y + _d[i].y].visited == false &&
			    f[pt.x + _d[i].x][pt.y + _d[i].y].avail == true) {
				ptnxt.x = pt.x + _d[i].x;
				ptnxt.y = pt.y + _d[i].y;
				queue__push(q, &ptnxt);
				f[ptnxt.x][ptnxt.y].enqueued = true;
				S_assert(f[ptnxt.x][ptnxt.y].visited == false);
				f[ptnxt.x][ptnxt.y].distance = f[pt.x][pt.y].distance + 1;
			}
		}
	}

	queue__cleanup(q);

	return ret;
}

int
main(int argc, char **argv)
{
	struct tile **f;
	int sx, sy, fx, fy;
	int i, n, ax, ay, bx, by;
	int j;

	scanf("%d%d%d%d", &sx, &sy, &fx, &fy);
	scanf("%d", &n);

	f = (struct tile **) s_calloc(41, sizeof *f);
	fprintf(stderr, "1;%lu\n", sizeof *f);
	fprintf(stderr, "2;%lu\n", sizeof f);
	for (i = 0; i < 41; i++)
		f[i] = (struct tile *) s_calloc(41, sizeof **f);

	for (i = 0; i < n; i++) {
		scanf("%d%d%d%d", &ax, &ay, &bx, &by);
		S_assert(ax == bx || ay == by);
#if 0
		fprintf(stderr, "ax=%d ay=%d bx=%d by=%d", ax, ay, bx, by);
		fflush(stderr);
#endif
		ax *= 2;
		ay *= 2;
		bx <<= 1;
		by <<= 1;
		if (ax == bx) {
			for (j = MIN(ay, by); j <= MAX(ay, by); j++)
				f[ax][j].avail = true;
		} else if (ay == by) {
			for (j = MIN(ax, bx); j <= MAX(ax, bx); j++)
				f[j][ay].avail = true;
		} else {
			fprintf(stderr, "failed to parse input data: ax=%d ay=%d bx=%d by=%d\n",
					ax / 2, ay / 2, bx / 2, by / 2);
		}
#if 0
		fprintf(stderr, " finished\n");
		fflush(stderr);
#endif
	}

	if (bfs_find_distance_grid(f, sx, sy, fx, fy) == 1)
		printf("%d\n", f[fx<<1][fy<<1].distance / 2);
	else
		puts("-1");

	for (i = 0; i < 41; i++) {
		free(f[i]);
		f[i] = NULL;
	}
	free(f);
	return 0;
}
